#include "CodeEdit.h"
#include "LineNumberArea.h"
#include "Highlighter.h"

#include "simodo/lsp-client/LspEnums.h"

#include <QtWidgets>

using namespace simodo;

LineNumberArea::LineNumberArea(CodeEdit *editor)
    : QWidget(editor)
    , _editor(editor)
{
    setContentsMargins(0,0,0,0);
    // setMouseTracking(true);
}

QSize LineNumberArea::sizeHint() const
{
    return QSize(_editor->calcLineNumberAreaWidth(), 0);
}

void LineNumberArea::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setFont(_editor->font());
    painter.fillRect(event->rect(), QColor(palette().color(backgroundRole())).lighter(100));

    int text_height = fontMetrics().height();

    QTextBlock block       = _editor->firstVisibleBlock();
    int        blockNumber = block.blockNumber();
    int        top         = qRound(_editor->blockBoundingGeometry(block).translated(_editor->contentOffset()).top());
    int        bottom      = top + qRound(_editor->blockBoundingRect(block).height());

    painter.setPen(QColor(palette().color(foregroundRole())).darker());

    Highlighter * highlighter = _editor->highlighter();

    while (block.isValid() && top <= event->rect().bottom()) {
        if (block.isVisible() && bottom >= event->rect().top()) {
            QString number_str = QString::number(blockNumber + 1) + " ";
            painter.drawText(0, top, width(), text_height, Qt::AlignRight, number_str);

            bool                    diagnostic_on_line = false;
            lsp::DiagnosticSeverity severity           = lsp::DiagnosticSeverity::Hint;
            
            if (highlighter)
                for(const shell::Diagnostic & d : highlighter->diagnostics())
                    if (d.range.start().line() == inout::position_line_t(blockNumber)) {
                        diagnostic_on_line = true;
                        severity = std::min(severity,d.severity);
                    }

            if (diagnostic_on_line) {
                std::u16string severity_str  = lsp::getDiagnosticSeverityString(severity);
                QString        severity_qstr = QString::fromStdU16String(severity_str);
                const QIcon    icon          = QIcon::fromTheme("dialog-"+severity_qstr, QIcon(":/images/dialog-"+severity_qstr));
                QPixmap        pixmap        = icon.pixmap(QSize(text_height, text_height));

                painter.drawPixmap(0, top, pixmap);
            }
        }

        block = block.next();
        top = bottom;
        bottom = top + qRound(_editor->blockBoundingRect(block).height());
        ++blockNumber;
    }
}

bool LineNumberArea::event(QEvent *event)
{
    if (event->type() == QEvent::ToolTip) {
        QHelpEvent *e      = static_cast<QHelpEvent *>(event);
        QTextBlock  block  = _editor->firstVisibleBlock();
        int         top    = static_cast<int>(_editor->blockBoundingGeometry(block).translated(_editor->contentOffset()).top());
        int         height = static_cast<int>(_editor->blockBoundingRect(block).height());

        QPoint p = e->pos();

        if (p.y() < top)
            return true;

        int mouse_line   = (p.y()-top) / height;
        int line_count   = _editor->document()->lineCount();
        int current_line = block.lineCount();

        if (mouse_line <= line_count - current_line) {
            if (p.x() >= 0 && p.x() < _editor->calcLineNumberAreaWidth()) {
                while(mouse_line > 0) {
                    if (!block.isValid())
                        return true;
                    block = block.next();
                    if (block.isVisible())
                        mouse_line --;
                }

                QString text = _editor->getErrorText(block.blockNumber());

                if (!text.isEmpty()) {
                    QToolTip::showText(e->globalPos(), text);
                }
                else {
                    QToolTip::hideText();
                    event->ignore();
                }
            }
        }

        return true;
    }

    return QWidget::event(event);
}


